/**
 * Project Name:pay-protocol
 * File Name:Xml.java
 * Package Name:cn.swiftpass.pay.protocol
 * Date:2014-8-10下午10:48:21
 */

package com.acooly.module.openapi.client.provider.fuyou.utils;

import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.CompactWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.security.AnyTypePermission;
import com.thoughtworks.xstream.security.NoTypePermission;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.TextUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;

/**
 * ClassName:Xml
 * Function: XML的工具方法
 * Date:     2014-8-10 下午10:48:21
 *
 * @author
 */
@Slf4j
public class XmlUtils {

    private static final String XML_HEAD = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>";
    private static final String XML_HEAD_YES = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
    /**
     * <一句话功能简述>
     * <功能详细描述>request转字符串
     *
     * @param request
     * @return
     * @see [类、类#方法、类#成员]
     */
    public static String parseRequst(HttpServletRequest request) {
        String body = "";
        try {
            ServletInputStream inputStream = request.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            while (true) {
                String info = br.readLine();
                if (info == null) {
                    break;
                }
                if (body == null || "".equals(body)) {
                    body = info;
                } else {
                    body += info;
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return body;
    }

    public static String parseXML(SortedMap<String, String> parameters) {
        StringBuffer sb = new StringBuffer();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (null != v && !"".equals(v) && !"appkey".equals(k)) {
                sb.append("<" + k + ">" + parameters.get(k) + "</" + k + ">\n");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

    /**
     * 从request中获得参数Map，并返回可读的Map
     *
     * @param request
     * @return
     */
    public static SortedMap getParameterMap(HttpServletRequest request) {
        // 参数Map
        Map properties = request.getParameterMap();
        // 返回值Map
        SortedMap returnMap = new TreeMap();
        Iterator entries = properties.entrySet().iterator();
        Map.Entry entry;
        String name = "";
        String value = "";
        while (entries.hasNext()) {
            entry = (Map.Entry) entries.next();
            name = (String) entry.getKey();
            Object valueObj = entry.getValue();
            if (null == valueObj) {
                value = "";
            } else if (valueObj instanceof String[]) {
                String[] values = (String[]) valueObj;
                for (int i = 0; i < values.length; i++) {
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length() - 1);
            } else {
                value = valueObj.toString();
            }
            returnMap.put(name, value.trim());
        }
        return returnMap;
    }

    /**
     * 转XMLmap
     *
     * @param xmlBytes
     * @param charset
     * @return
     * @throws Exception
     * @author
     */
    public static Map<String, String> toMap(byte[] xmlBytes, String charset) throws Exception {
        SAXReader reader = new SAXReader(false);
        InputSource source = new InputSource(new ByteArrayInputStream(xmlBytes));
        source.setEncoding(charset);
        Document doc = reader.read(source);
        Map<String, String> params = XmlUtils.toMap(doc.getRootElement());
        return params;
    }

    /**
     * 转MAP
     *
     * @param element
     * @return
     * @author
     */
    public static Map<String, String> toMap(Element element) {
        Map<String, String> rest = new HashMap<String, String>();
        List<Element> els = element.elements();
        for (Element el : els) {
            rest.put(el.getName().toLowerCase(), el.getTextTrim());
        }
        return rest;
    }

    /**
     * 利用xStream将xml报文转化为实体
     *
     * @param xmlStr
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> T toBean(String xmlStr, Class<T> cls) {
        if (TextUtils.isEmpty(xmlStr) || xmlStr.contains("Error")) {
            return null;
        }
        try {
            XStream xstream = new XStream(new DomDriver());
//            XStream.setupDefaultSecurity(xstream);
            xstream.addPermission(AnyTypePermission.ANY);
            xstream.addPermission(NoTypePermission.NONE);
            //忽略不需要的节点
            xstream.ignoreUnknownElements();
            //对指定的类使用Annotations 进行序列化
            xstream.processAnnotations(cls);
            xstream.allowTypes(new Class[]{cls});
            T obj = (T) xstream.fromXML(xmlStr);
            return obj;
        } catch (Exception e) {
            throw new ApiClientException("响应报文转化失败："+e.getMessage());
        }
    }

    /**
     * 利用xStream将实体报文转化为xml
     *
     * @param obj
     * @return
     */
    public static String toXml(Object obj,boolean isStandalone) {
        try {
            XStream xstream = new XStream(new DomDriver("UTF-8", new NoNameCoder()));
            //1.4.10配置安全框架
//            XStream.setupDefaultSecurity(xstream);
            //1。4.9配置安全框架
            xstream.addPermission(AnyTypePermission.ANY);
            xstream.addPermission(NoTypePermission.NONE);
            //忽略不需要的节点
            xstream.ignoreUnknownElements();
            //对指定的类使用Annotations 进行序列化
            xstream.processAnnotations(obj.getClass());
            String returnXml = xstream.toXML(obj);
            if(isStandalone) {
                return XML_HEAD_YES+returnXml;
            } else {
                return XML_HEAD+returnXml;
            }

        } catch (Exception e) {
            throw new ApiClientException("请求报文转化失败："+e.getMessage());
        }
    }

    /**
     * 去掉xml多余的空白、换行符
     */
    public static String trimXml(String xml) {
        String result = xml;
        if (null != result) {
            result = result.replaceAll(">\\s+<", "><");
        }
        return result;
    }
}

